const std = @import("std");
const Allocator = std.mem.Allocator;

/// 动态列表 - 需要显式传入分配器
pub fn List(comptime T: type) type {
    return struct {
        const Self = @This();
        
        items: []T,
        capacity: usize,
        len: usize,
        allocator: Allocator,
        
        pub fn init(allocator: Allocator) !Self {
            return Self{
                .items = &[_]T{},
                .capacity = 0,
                .len = 0,
                .allocator = allocator,
            };
        }
        
        pub fn deinit(self: *Self) void {
            if (self.capacity > 0) {
                self.allocator.free(self.items);
            }
        }
        
        pub fn append(self: *Self, item: T) !void {
            if (self.len >= self.capacity) {
                try self.grow();
            }
            self.items[self.len] = item;
            self.len += 1;
        }
        
        fn grow(self: *Self) !void {
            const new_capacity = if (self.capacity == 0) 8 else self.capacity * 2;
            const new_items = try self.allocator.alloc(T, new_capacity);
            
            if (self.len > 0) {
                @memcpy(new_items[0..self.len], self.items[0..self.len]);
            }
            
            if (self.capacity > 0) {
                self.allocator.free(self.items);
            }
            
            self.items = new_items;
            self.capacity = new_capacity;
        }
        
        pub fn get(self: *const Self, index: usize) ?T {
            if (index >= self.len) return null;
            return self.items[index];
        }
    };
}

test "list operations" {
    const testing = std.testing;
    
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    
    var list = try List(u32).init(gpa.allocator());
    defer list.deinit();
    
    try list.append(10);
    try list.append(20);
    try list.append(30);
    
    try testing.expectEqual(@as(usize, 3), list.len);
    try testing.expectEqual(@as(u32, 10), list.get(0).?);
    try testing.expectEqual(@as(u32, 20), list.get(1).?);
}
